﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PayloadTracker.APRS.Parsers
{
    public class GPRMC : IParser
    {
        /*
         $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A

            Where:
                 RMC          Recommended Minimum sentence C
                 123519       Fix taken at 12:35:19 UTC
                 A            Status A=active or V=Void.
                 4807.038,N   Latitude 48 deg 07.038' N
                 01131.000,E  Longitude 11 deg 31.000' E
                 022.4        Speed over the ground in knots
                 084.4        Track angle in degrees True
                 230394       Date - 23rd of March 1994
                 003.1,W      Magnetic Variation
                 *6A          The checksum data, always begins with *
*/
        enum GPRMCParts : int
        {
            SENTENCEIDENTIFIER = 0,
            UTCTIME = 1,
            STATUS = 2,
            LATITUDE = 3,
            LATITUDEBEARING = 4,
            LONGITUDE = 5,
            LONGITUDEBEARING = 6,
            SPEED = 7,
            TRACKANGLE = 8,
            DATE = 9,
            MAGNETICVARIATION= 10,
            MAGNETICVARIATIONBEARING = 11,
            
        }
        public struct GPRMCExtraData
        {
            public string Date;
            public string MagneticVariation;
            public string MagneticVariationBearing;
            public string Status;
        }

        public override APRSBeacon Parse(string sentence)
        {
            if (!IsValidSentence(sentence))
                //throw new Exception("Invalid Sentence");
                return null;

            var csv = Tools.NMEAWords(sentence);
            switch (csv[((int)GPRMCParts.STATUS)])
            {
                case "A":
                    //valid fix, keep processing
                    break;
                default:
                    //no fix, stop processing
                    return null;
            }


            double Long = Tools.GPSToDecimalDegrees(csv[((int)GPRMCParts.LONGITUDE)], csv[((int)GPRMCParts.LONGITUDEBEARING)]);
            double Lat = Tools.GPSToDecimalDegrees(csv[((int)GPRMCParts.LATITUDE)], csv[((int)GPRMCParts.LATITUDEBEARING)]);
            float Course = 0;
            try
            {
                Course = float.Parse(csv[((int)GPRMCParts.TRACKANGLE)]);
            }
            catch (Exception)
            { }
            float Speed = 0;
            try
            {
                Tools.KnotsToMPH(double.Parse(csv[((int)GPRMCParts.SPEED)]));
            }
            catch (Exception)
            { }
            //DateTime Time = Tools.NMEAUTCTimeToUTCDateTime(csv[((int)GPRMCParts.UTCTIME)]);
            DateTime Time = Tools.NMEAUTCTimeToLocalTime(csv[((int)GPRMCParts.UTCTIME)]);

            APRSBeacon ret = new APRSBeacon(string.Empty, new Coordinate(Lat, Long), Time, float.MinValue, Course, Speed);
            return ret;
        }

        public GPRMCExtraData GetExtraData(string sentence)
        {
            if (!IsValidSentence(sentence))
                throw new Exception("Invalid Sentence");
                
            var csv = sentence.Split(',');

            GPRMCExtraData ret = new GPRMCExtraData();

            ret.Date = csv[((int)GPRMCParts.DATE)];
            ret.MagneticVariation = csv[((int)GPRMCParts.MAGNETICVARIATION)];
            ret.MagneticVariationBearing = csv[((int)GPRMCParts.MAGNETICVARIATIONBEARING)];
            ret.Status = csv[((int)GPRMCParts.STATUS)];

            return ret;

        }

        public override bool IsValidSentence(string sentence)
        {
            if (!sentence.StartsWith("$GPRMC"))
                return false;

            //Checksum
            int crc = Convert.ToByte(sentence[1]);
            for (int i = 2; i < sentence.Length - 3; i++)
                crc ^= Convert.ToByte(sentence[i]);

            return sentence.EndsWith("*" + crc.ToString("X2"));

        }
    }
}
